package xin.alum.aim.model;

import com.google.protobuf.Any;
import com.google.protobuf.Message;
import lombok.Data;
import lombok.SneakyThrows;
import xin.alum.aim.constant.AimConstant;
import xin.alum.aim.util.GZipUtil;

import java.io.Serializable;

/**
 * 基于ProtoBuy的数据通信抽象类
 */
@Data
public class Events<T extends Message> extends Transportable implements Serializable {

    /**
     * 返回数据集合
     */
    protected T data;
    /**
     * 返回码
     */
    private Integer code;
    /**
     * 返回描述
     */
    private String message;
    /**
     * 请求key
     */
    private String key = "";

    public Events() {
        super();
    }

    public Events(String key) {
        super();
        this.key = key;
    }

    public Events(String key, String message) {
        super();
        this.key = key;
        this.message = message;
    }

    public Events(String key, long timestamp) {
        super();
        this.key = key;
        super.setTimestamp(timestamp);
    }

    public Events(String key, T data) {
        super();
        this.key = key;
        this.data = data;
    }

    public Events(String key, long timestamp, T data) {
        super();
        this.key = key;
        this.setTimestamp(timestamp);
        this.data = data;
    }


    /**
     * 转换ProtoBuf
     *
     * @return
     */
    private Message toMessage() {
        Aim.Packet.Builder b = Aim.Packet.newBuilder();
        if (code != null) {
            b.setCode(code);
        }
        if (key != null) {
            b.setKey(key);
        }
        if (getPriority() != null) {
            b.setPriority(getPriority());
        }
        if (getRecipient() != null) {
            b.setRecipient(getRecipient());
        }
        if (message != null) {
            b.setMessage(message);
        }
        if (getTimestamp() != null) {
            b.setTimestamp(getTimestamp());
        }
        if (data != null) {
            if(data instanceof Any)
            {
                b.setData((Any) data);
            }else {
                b.setData(Any.pack(data));
            }
        }
        return b.build();
    }

    /**
     * 将Data解包成Message对象
     *
     * @param clazz 解包目录类
     * @return
     */
    @SneakyThrows
    public T unpack(Class<T> clazz) {
        return ((Any) data).unpack(clazz);
    }

    /**
     * @return
     */
    @Override
    public byte[] toBytes() {
        if (body == null) {
            body = GZipUtil.gzip(xin.alum.aim.Aim.properties.getGzip(), toMessage().toByteArray());
        }
        return body;
    }

    @Override
    public int getTag() {
        return AimConstant.DATA_TYPE_REPLY;
    }

    @Override
    public String toString() {
        try {
            return new ProtoUtil(data.getDescriptorForType()).toJson(toMessage());
        } catch (Exception e) {
            logger.error(e);
            return "";
        }
    }
}
